package com.och.mrcp.core.sip.transaction;

import com.och.mrcp.core.sip.model.SipRequest;
import com.och.mrcp.core.sip.model.SipResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class SipTransactionManager {
    
    private final Map<String, SipTransaction> transactions = new ConcurrentHashMap<>();
    // 优化为多线程调度器，提高并发处理能力
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(4, r -> {
        Thread t = new Thread(r, "SipTransactionManager-Scheduler");
        t.setDaemon(true);
        return t;
    });
    
    public SipTransactionManager() {
        // 启动定时清理过期事务的任务
        scheduler.scheduleAtFixedRate(this::cleanupExpiredTransactions, 30, 30, TimeUnit.SECONDS);
    }
    
    public SipTransaction createClientTransaction(SipRequest request, SipTransaction.Type type) {
        SipTransaction transaction = new SipTransaction(request, type);
        transactions.put(transaction.getTransactionId(), transaction);
        
        log.debug("Created client transaction: {}", transaction);
        return transaction;
    }
    
    public SipTransaction createServerTransaction(SipRequest request, SipTransaction.Type type) {
        SipTransaction transaction = new SipTransaction(request, type);
        transactions.put(transaction.getTransactionId(), transaction);
        
        log.debug("Created server transaction: {}", transaction);
        return transaction;
    }
    
    public SipTransaction findTransaction(String transactionId) {
        return transactions.get(transactionId);
    }
    
    public SipTransaction findTransactionByRequest(SipRequest request) {
        String transactionId = generateTransactionId(request);
        return transactions.get(transactionId);
    }
    
    public SipTransaction findTransactionByResponse(SipResponse response) {
        // 通过响应查找对应的事务
        for (SipTransaction transaction : transactions.values()) {
            if (transaction.getOriginalRequest() != null &&
                transaction.getOriginalRequest().getCallId().equals(response.getCallId()) &&
                transaction.getOriginalRequest().getCseq().equals(response.getCseq())) {
                return transaction;
            }
        }
        return null;
    }
    
    public void updateTransaction(SipTransaction transaction) {
        if (transaction != null) {
            transactions.put(transaction.getTransactionId(), transaction);
            log.debug("Updated transaction: {}", transaction);
        }
    }
    
    public void removeTransaction(String transactionId) {
        SipTransaction transaction = transactions.remove(transactionId);
        if (transaction != null) {
            log.debug("Removed transaction: {}", transaction);
        }
    }
    
    public void removeTransaction(SipTransaction transaction) {
        if (transaction != null) {
            removeTransaction(transaction.getTransactionId());
        }
    }
    
    public void cleanupExpiredTransactions() {
        transactions.entrySet().removeIf(entry -> {
            SipTransaction transaction = entry.getValue();
            if (transaction.isExpired()) {
                log.debug("Cleaning up expired transaction: {}", transaction);
                transaction.terminate();
                return true;
            }
            return false;
        });
        
        log.debug("Transaction cleanup completed. Active transactions: {}", transactions.size());
    }
    
    public void shutdown() {
        scheduler.shutdown();
        try {
            if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
                scheduler.shutdownNow();
            }
        } catch (InterruptedException e) {
            scheduler.shutdownNow();
            Thread.currentThread().interrupt();
        }
        
        // 清理所有事务
        transactions.values().forEach(SipTransaction::terminate);
        transactions.clear();
        
        log.info("SIP Transaction Manager shutdown completed");
    }
    
    private String generateTransactionId(SipRequest request) {
        return request.getCallId() + "-" + request.getCseq() + "-" + request.getMethod();
    }
    
    public int getActiveTransactionCount() {
        return transactions.size();
    }
    
    public Map<String, SipTransaction> getAllTransactions() {
        return new ConcurrentHashMap<>(transactions);
    }
}
